#include "t0022-0.h"
#include "cui.h"

#define MODNAME             "[CTXT]"
/*
"attributes":{
    "name": "dataview",
    "layout": "appdata/dataview",
    "actionlist":[],
    "border": 1,
    "title": "",
    "text": [
        {
            "forecolor": "white",
            "backcolor": "black",
            "beginx": 0,
            "beginy": 0
        },
        {
            "forecolor": "white",
            "backcolor": "black",
            "beginx": 0,
            "beginy": 1
        },
        {
            "forecolor": "white",
            "backcolor": "black",
            "beginx": 0,
            "beginy": 2
        }
    ]
},
*/

static const char* cui_get_colorpair_string(int colorpair)
{
    switch (colorpair) {
        case WHTBLK:
        return "white/black";
        case REDBLK:
        return "red/black";
        case GRNBLK:
        return "green/black";
        case BLUBLK:
        return "blue/black";
        case CYNBLK:
        return "cyan/black";
        case YELBLK:
        return "yellow/black";
        case BLKWHT:
        return "black/white";
        case BLKRED:
        return "black/red";
        case BLKGRN:
        return "black/green";
        case BLKBLU:
        return "black/blue";
        case BLKCYN:
        return "black/cyan";
        case BLKYEL:
        return "black/yellow";
    }
    return "unknown";
}

static int cui_get_colorcode(const char *color)
{
    if (is_string_equal_safe(color, COLOR_BLACK_STR)) {
        return COLOR_BLACK;
    }
    if (is_string_equal_safe(color, COLOR_WHITE_STR)) {
        return COLOR_WHITE;
    }
    if (is_string_equal_safe(color, COLOR_RED_STR)) {
        return COLOR_RED;
    }
    if (is_string_equal_safe(color, COLOR_GREEN_STR)) {
        return COLOR_GREEN;
    }
    if (is_string_equal_safe(color, COLOR_BLUE_STR)) {
        return COLOR_BLUE;
    }
    if (is_string_equal_safe(color, COLOR_CYAN_STR)) {
        return COLOR_CYAN;
    }
    if (is_string_equal_safe(color, COLOR_YELLOW_STR)) {
        return COLOR_YELLOW;
    }
    return -1;
}

static int cui_get_colorpair(int fore, int back) 
{
    if (back == COLOR_BLACK) {
        switch (fore) {
            case COLOR_WHITE:
            return WHTBLK;
            case COLOR_RED:
            return REDBLK;
            case COLOR_GREEN:
            return GRNBLK;
            case COLOR_BLUE:
            return BLUBLK;
            case COLOR_CYAN:
            return CYNBLK;
            case COLOR_YELLOW:
            return YELBLK;
        }
    }
    if (fore == COLOR_BLACK) {
        switch (back) {
            case COLOR_WHITE:
            return BLKWHT;
            case COLOR_RED:
            return BLKRED;
            case COLOR_GREEN:
            return BLKGRN;
            case COLOR_BLUE:
            return BLKBLU;
            case COLOR_CYAN:
            return BLKCYN;
            case COLOR_YELLOW:
            return BLKYEL;
        }
    }

    return -1;
}

int cui_label_parse(cJSON *attr, struct cui_widget_st* widget)
{
    // root指向attributes
    int retval = -1;
    cJSON *node; 
    cJSON *textlist;
    cJSON *text;
    textlist = cJSON_GetObjectItem(attr, CUI_CONFIELD_LABEL);
    if (cJSON_ValidArray(textlist)) {
        int i;
        int nlabels = cJSON_GetArraySize(textlist);
        struct cui_label_st *clabel = zmalloc(nlabels * sizeof(struct cui_label_st));
        if (clabel != NULL) {
            for (i = 0;i < nlabels;i ++) {
                int backcolor = -1, forecolor = -1;
                text = cJSON_GetArrayItem(textlist, i);
                node = cJSON_GetObjectItem(text, CUI_CONFIELD_FORECOLOR);
                if(cJSON_ValidString(node) == 0){
                    forecolor = cui_get_colorcode(node->valuestring);
                }
                if (forecolor < 0) {
                    forecolor = COLOR_WHITE;
                }
                node = cJSON_GetObjectItem(text, CUI_CONFIELD_BACKCOLOR);
                if(cJSON_ValidString(node) == 0){
                    backcolor = cui_get_colorcode(node->valuestring);
                }
                if (backcolor < 0) {
                    backcolor = COLOR_BLACK;
                }
                clabel[i].color = cui_get_colorpair(forecolor, backcolor);
                node = cJSON_GetObjectItem(text, CUI_CONFIELD_BEGINX);
                if (cJSON_ValidNumber(node)) {
                    clabel[i].beginx = node->valueint;
                }
                node = cJSON_GetObjectItem(text, CUI_CONFIELD_BEGINY);
                if (cJSON_ValidNumber(node)) {
                    clabel[i].beginy = node->valueint;
                }
                node = cJSON_GetObjectItem(text, CUI_CONFIELD_TEXT);
                if (cJSON_ValidString(node)) {
                    strncpy(clabel[i].text, node->valuestring, CUI_WIDGETTITLE_BUFLEN);
                }
                ERRSYS_INFOPRINT("[%s] x %d y %d color %s name %s\n", widget->name, clabel[i].beginx, clabel[i].beginy, cui_get_colorpair_string(clabel[i].color), clabel[i]);
            }
            widget->clabel = clabel;
            widget->nlabels = nlabels;
            ERRSYS_INFOPRINT("[%s] nlabels %d\n", widget->name, nlabels);
            retval = 0;
        }
        else {
            ERRSYS_INFOPRINT("[%s]Fail to malloc ctext\n", widget->name);
        }
    }

    return retval;
}


void cui_text_set_label(struct cui_widget_st *widget, int index, const char *label)
{
    if (widget != NULL) {
        struct cui_label_st *clabel = widget->clabel;
        if (widget->nlabels > 0 && index < widget->nlabels) {
            int n = strlen(label) + 1;  // "\0" included
            strncpy(clabel[index].text, label, CUI_WIDGETTITLE_BUFLEN);
            if (n >= CUI_WIDGETTITLE_BUFLEN) {
                clabel[index].text[CUI_WIDGETTITLE_BUFLEN - 1] = 0;
            }
        }
    }
}

void cui_text_flushchar(struct cui_widget_st *widget, int index, char flush_char)
{
    if (widget != NULL) {
        struct cui_label_st *clabel = widget->clabel;
        if (widget->nlabels > 0 && index < widget->nlabels) {
            int n = strlen(clabel[index].text);
            if (n > CUI_WIDGETTITLE_BUFLEN) {
                n = CUI_WIDGETTITLE_BUFLEN - 1;
                clabel[index].text[n] = 0;
            }
            else if (n > 0) {
                clabel[index].text[n] = 0;
            }
            // fill blanks
            if (n > 0) {
                memset(clabel[index].text, flush_char, n);
            }
        }
    }
}

int strlen_trimtails(const char *stream)
{
    int length = strlen(stream);
    int i;
    int retval = length;
    for (i = length - 1;i > 0;i --) {
        if (stream[i] == ' ' || stream[i] == '\t') {
            retval --;
        }
        else {
            break;
        }
    }
    return retval;
}

int cui_label_printf(struct cui_widget_st *widget, int index, const char* stream, ...)
{
	int retval = -1;
    if (widget != NULL) {
        if (widget->nlabels > 0 && index < widget->nlabels) {
            struct cui_label_st *clabel = &widget->clabel[index];
            int oldlength = strlen_trimtails(clabel->text);
            int newlength = 0;
            va_list arg_ptr;
            va_start(arg_ptr, stream);
            // ERRSYS_INFOPRINT("!!!!!! old label \"%s\" length %d\n", clabel->text, oldlength);
            retval = vsnprintf(clabel->text, CUI_WIDGETTITLE_BUFLEN, stream, arg_ptr);
            newlength = strlen(clabel->text);
            // ERRSYS_INFOPRINT("!!!!!!! new label length %d\n", newlength);
            if (newlength < oldlength) {
                memset(&clabel->text[newlength], ' ', oldlength - newlength);
            	clabel->text[oldlength] = 0;
                // ERRSYS_INFOPRINT("!!!!!!! replace blank, new length %d\n", strlen(clabel->text));
            }
            // ERRSYS_INFOPRINT("!!!!!!! new label \"%s\"\n", clabel->text);

            va_end(arg_ptr);
        }
    }
    return retval;
}